<template>
  <div class="main-wrap">
    <div class="top-wrap">
      <div class="left-wrap">
        <el-descriptions title="流水线-流程配置" :column="1" direction="horizontal">
          <el-descriptions-item label="任务名称:">
            <span class="task-text">{{ taskInfo.name }}</span>
          </el-descriptions-item>
          <el-descriptions-item label="命名空间:">
            <span class="task-text">{{ taskInfo.namespaceRel }}</span>
          </el-descriptions-item>
        </el-descriptions>
      </div>
      <div class="right-wrap">
        <div style="margin-right: 10px; min-width: 120px">
          <el-select v-model="selectTemplate" @change="templateChange" placeholder="选择模版">
            <el-option
                v-for="item in templateList"
                :key="item.id"
                :label="item.name"
                :value="item.id"
            >
              <span style="float: left; margin-right: 20px;">{{ item.name }}</span>
              <span @click.stop="handleDeleteTemplate(item.id)" style="float: right; color: var(--el-text-color-secondary); font-size: 13px; color: #F56C6C;">删除</span>
            </el-option>
          </el-select>
        </div>
        <el-button type="primary" @click="handleSaveTemplate">保存为模版</el-button>
        <el-button type="success" @click="handleSaveFlow">保存流程</el-button>
      </div>
    </div>
    <div class="task-flow-wrap">
      <div class="app-stencil" ref="stencilDom"/>
      <div class="app-content" ref="graphDom"/>
      <TeleportContainer />
    </div>

    <!-- git -->
    <el-drawer v-model="drawerData.GIT.drawerFlag" :direction="direction" size="500" :with-header="false">
      <el-form :model="drawerData.GIT.nodeData" label-position="top">
        <el-form-item label="节点id:" required>
          <el-input v-model="drawerData.GIT.nodeData.id" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点类型:" required>
          <el-input v-model="drawerData.GIT.nodeData.type" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点名称:" required>
          <el-input v-model="drawerData.GIT.nodeData.title" maxlength="8" show-word-limit clearable/>
        </el-form-item>
        <el-form-item label="git仓库地址:" required>
          <el-input v-model="drawerData.GIT.nodeData.data.url" type="textarea" maxlength="600" show-word-limit clearable/>
        </el-form-item>
        <el-form-item label="git密钥:" required>
          <el-select v-model="drawerData.GIT.nodeData.data.secretName" clearable placeholder="请选择密钥">
            <template #header>
              <el-row>
                <el-col :span="12">
                  <router-link :to="{name: 'secret'}" target="_blank">添加密钥</router-link>
                </el-col>
                <el-col :span="12" style="display: flex; justify-content: flex-end; align-items: center;">
                  <el-button :icon="Refresh" size="small" circle :loading="secretRefreshFlag" @click="handleSecretRefresh"/>
                </el-col>
              </el-row>
            </template>
            <el-option
                v-for="(item,index) in gitSecretList"
                :key="index"
                :label="item.name"
                :value="item.name"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="默认分支:" required>
          <el-input v-model="drawerData.GIT.nodeData.data.defaultBranch" clearable/>
        </el-form-item>
        <el-form-item label="选择分支:">
          <el-input v-model="drawerData.GIT.nodeData.data.branch" clearable />
        </el-form-item>
      </el-form>
    </el-drawer>

    <!-- maven -->
    <el-drawer v-model="drawerData.MAVEN.drawerFlag" :direction="direction" size="500" :with-header="false">
      <el-form :model="drawerData.MAVEN.nodeData" label-position="top">
        <el-form-item label="节点id:" required>
          <el-input v-model="drawerData.MAVEN.nodeData.id" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点类型:" required>
          <el-input v-model="drawerData.MAVEN.nodeData.type" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点名称:" required>
          <el-input v-model="drawerData.MAVEN.nodeData.title" maxlength="8" show-word-limit clearable />
        </el-form-item>
        <el-form-item label="maven版本:" required>
          <el-select v-model="drawerData.MAVEN.nodeData.data.dockerImage" clearable placeholder="请选择镜像版本">
            <template #header>
              <el-row>
                <el-col :span="12">
                  <router-link :to="{name: 'nodeImage'}" target="_blank">添加镜像</router-link>
                </el-col>
                <el-col :span="12" style="display: flex; justify-content: flex-end; align-items: center;">
                  <el-button :icon="Refresh" size="small" circle :loading="secretRefreshFlag" @click="handleImageRefresh"/>
                </el-col>
              </el-row>
            </template>
            <el-option
                v-for="item in mavenImages"
                :key="item.id"
                :label="item.dockerImage"
                :value="item.dockerImage"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="执行命令:" required>
          <el-input v-model="drawerData.MAVEN.nodeData.data.command" clearable />
        </el-form-item>
        <el-form-item label="pom文件地址:">
          <el-input v-model="drawerData.MAVEN.nodeData.data.pomPath" clearable />
        </el-form-item>
        <el-form-item label="工作目录:">
          <el-input v-model="drawerData.MAVEN.nodeData.data.workDir" clearable />
        </el-form-item>
      </el-form>
    </el-drawer>

    <!-- docker -->
    <el-drawer v-model="drawerData.DOCKER.drawerFlag" :direction="direction" size="500" :with-header="false">
      <el-form :model="drawerData.DOCKER.nodeData" label-position="top">
        <el-form-item label="节点id:" required>
          <el-input v-model="drawerData.DOCKER.nodeData.id" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点类型:" required>
          <el-input v-model="drawerData.DOCKER.nodeData.type" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点名称:" required>
          <el-input v-model="drawerData.DOCKER.nodeData.title" maxlength="8" show-word-limit clearable />
        </el-form-item>
        <el-form-item label="镜像名称:" required>
          <el-input v-model="drawerData.DOCKER.nodeData.data.name" clearable />
        </el-form-item>
        <el-form-item label="镜像版本:" required>
          <el-input v-model="drawerData.DOCKER.nodeData.data.version" clearable />
        </el-form-item>
        <el-form-item label="dockerFile:" required>
          <el-input v-model="drawerData.DOCKER.nodeData.data.dockerFile" clearable />
        </el-form-item>
        <el-form-item label="构建地址:" required>
          <el-input v-model="drawerData.DOCKER.nodeData.data.buildPath" clearable />
        </el-form-item>
        <el-form-item label="镜像仓库:">
          <el-input v-model="drawerData.DOCKER.nodeData.data.registry" placeholder="docker镜像仓库地址" type="textarea" maxlength="600" show-word-limit clearable />
        </el-form-item>
        <el-form-item label="镜像仓库密钥:">
          <el-select v-model="drawerData.DOCKER.nodeData.data.secretName" clearable placeholder="请选择密钥">
            <template #header>
              <el-row>
                <el-col :span="12">
                  <router-link :to="{name: 'secret'}" target="_blank">添加密钥</router-link>
                </el-col>
                <el-col :span="12" style="display: flex; justify-content: flex-end; align-items: center;">
                  <el-button :icon="Refresh" size="small" circle :loading="secretRefreshFlag" @click="handleSecretRefresh"/>
                </el-col>
              </el-row>
            </template>
            <el-option
                v-for="(item,index) in dockerSecretList"
                :key="index"
                :label="item.name"
                :value="item.name"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="后置命令:">
          <el-input v-model="drawerData.DOCKER.nodeData.data.afterCmd" placeholder="构建后执行命令" type="textarea" maxlength="600" show-word-limit clearable />
        </el-form-item>
        <el-form-item label="工作目录:">
          <el-input v-model="drawerData.DOCKER.nodeData.data.workDir" clearable />
        </el-form-item>
      </el-form>
    </el-drawer>

    <!-- k8s -->
    <el-drawer v-model="drawerData.K8S.drawerFlag" :direction="direction" size="500" :with-header="false">
      <el-form :model="drawerData.K8S.nodeData" label-position="top">
        <el-form-item label="节点id:" required>
          <el-input v-model="drawerData.K8S.nodeData.id" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点类型:" required>
          <el-input v-model="drawerData.K8S.nodeData.type" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点名称:" required>
          <el-input v-model="drawerData.K8S.nodeData.title" maxlength="8" show-word-limit clearable />
        </el-form-item>
        <el-form-item label="k8s服务地址:" required>
          <el-input v-model="drawerData.K8S.nodeData.data.apiServer" clearable />
        </el-form-item>
        <el-form-item label="k8s密钥:" required>
          <el-select v-model="drawerData.K8S.nodeData.data.secretName" clearable placeholder="请选择密钥">
            <template #header>
              <el-row>
                <el-col :span="12">
                  <router-link :to="{name: 'secret'}" target="_blank">添加密钥</router-link>
                </el-col>
                <el-col :span="12" style="display: flex; justify-content: flex-end; align-items: center;">
                  <el-button :icon="Refresh" size="small" circle :loading="secretRefreshFlag" @click="handleSecretRefresh"/>
                </el-col>
              </el-row>
            </template>
            <el-option
                v-for="(item,index) in k8sSecretList"
                :key="index"
                :label="item.name"
                :value="item.name"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="部署文件地址:" required>
          <el-input v-model="drawerData.K8S.nodeData.data.filePath" clearable />
        </el-form-item>
        <el-form-item label="工作目录:">
          <el-input v-model="drawerData.K8S.nodeData.data.workDir" clearable />
        </el-form-item>
      </el-form>
    </el-drawer>

    <!-- nodeJs -->
    <el-drawer v-model="drawerData.NODEJS.drawerFlag" :direction="direction" size="500" :with-header="false">
      <el-form :model="drawerData.NODEJS.nodeData" label-position="top">
        <el-form-item label="节点id:" required>
          <el-input v-model="drawerData.NODEJS.nodeData.id" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点类型:" required>
          <el-input v-model="drawerData.NODEJS.nodeData.type" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点名称:" required>
          <el-input v-model="drawerData.NODEJS.nodeData.title" maxlength="8" show-word-limit clearable />
        </el-form-item>
        <el-form-item label="node版本:" required>
          <el-select v-model="drawerData.NODEJS.nodeData.data.dockerImage" clearable placeholder="请选择镜像版本">
            <template #header>
              <el-row>
                <el-col :span="12">
                  <router-link :to="{name: 'nodeImage'}" target="_blank">添加镜像</router-link>
                </el-col>
                <el-col :span="12" style="display: flex; justify-content: flex-end; align-items: center;">
                  <el-button :icon="Refresh" size="small" circle :loading="secretRefreshFlag" @click="handleImageRefresh"/>
                </el-col>
              </el-row>
            </template>
            <el-option
                v-for="item in nodeImages"
                :key="item.id"
                :label="item.dockerImage"
                :value="item.dockerImage"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="执行命令:" required>
          <el-input v-model="drawerData.NODEJS.nodeData.data.command" type="textarea" maxlength="300" clearable />
        </el-form-item>
        <el-form-item label="工作目录:">
          <el-input v-model="drawerData.NODEJS.nodeData.data.workDir" clearable />
        </el-form-item>
      </el-form>
    </el-drawer>

    <!-- go -->
    <el-drawer v-model="drawerData.GO.drawerFlag" :direction="direction" size="500" :with-header="false">
      <el-form :model="drawerData.GO.nodeData" label-position="top">
        <el-form-item label="节点id:" required>
          <el-input v-model="drawerData.GO.nodeData.id" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点类型:" required>
          <el-input v-model="drawerData.GO.nodeData.type" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点名称:" required>
          <el-input v-model="drawerData.GO.nodeData.title" maxlength="8" show-word-limit clearable />
        </el-form-item>
        <el-form-item label="go版本:" required>
          <el-select v-model="drawerData.GO.nodeData.data.dockerImage" clearable placeholder="请选择镜像版本">
            <template #header>
              <el-row>
                <el-col :span="12">
                  <router-link :to="{name: 'nodeImage'}" target="_blank">添加镜像</router-link>
                </el-col>
                <el-col :span="12" style="display: flex; justify-content: flex-end; align-items: center;">
                  <el-button :icon="Refresh" size="small" circle :loading="secretRefreshFlag" @click="handleImageRefresh"/>
                </el-col>
              </el-row>
            </template>
            <el-option
                v-for="item in goImages"
                :key="item.id"
                :label="item.dockerImage"
                :value="item.dockerImage"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="执行命令:" required>
          <el-input v-model="drawerData.GO.nodeData.data.command" type="textarea" maxlength="300" clearable />
        </el-form-item>
        <el-form-item label="代理(GOPROXY):" required>
          <el-input v-model="drawerData.GO.nodeData.data.goProxy" type="textarea" maxlength="300" clearable />
        </el-form-item>
        <el-form-item label="工作目录:">
          <el-input v-model="drawerData.GO.nodeData.data.workDir" clearable />
        </el-form-item>
      </el-form>
    </el-drawer>

    <!-- cmake -->
    <el-drawer v-model="drawerData.CMAKE.drawerFlag" :direction="direction" size="500" :with-header="false">
      <el-form :model="drawerData.CMAKE.nodeData" label-position="top">
        <el-form-item label="节点id:" required>
          <el-input v-model="drawerData.CMAKE.nodeData.id" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点类型:" required>
          <el-input v-model="drawerData.CMAKE.nodeData.type" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点名称:" required>
          <el-input v-model="drawerData.CMAKE.nodeData.title" maxlength="8" show-word-limit clearable />
        </el-form-item>
        <el-form-item label="cmake版本:" required>
          <el-select v-model="drawerData.CMAKE.nodeData.data.dockerImage" clearable placeholder="请选择镜像版本">
            <template #header>
              <el-row>
                <el-col :span="12">
                  <router-link :to="{name: 'nodeImage'}" target="_blank">添加镜像</router-link>
                </el-col>
                <el-col :span="12" style="display: flex; justify-content: flex-end; align-items: center;">
                  <el-button :icon="Refresh" size="small" circle :loading="secretRefreshFlag" @click="handleImageRefresh"/>
                </el-col>
              </el-row>
            </template>
            <el-option
                v-for="item in cmakeImages"
                :key="item.id"
                :label="item.dockerImage"
                :value="item.dockerImage"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="执行命令:" required>
          <el-input v-model="drawerData.CMAKE.nodeData.data.command" type="textarea" maxlength="300" clearable />
        </el-form-item>
        <el-form-item label="工作目录:">
          <el-input v-model="drawerData.CMAKE.nodeData.data.workDir" clearable />
        </el-form-item>
      </el-form>
    </el-drawer>

    <!-- ssh -->
    <el-drawer v-model="drawerData.SSH.drawerFlag" :direction="direction" size="500" :with-header="false">
      <el-form :model="drawerData.SSH.nodeData" label-position="top">
        <el-form-item label="节点id:" required>
          <el-input v-model="drawerData.SSH.nodeData.id" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点类型:" required>
          <el-input v-model="drawerData.SSH.nodeData.type" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点名称:" required>
          <el-input v-model="drawerData.SSH.nodeData.title" maxlength="8" show-word-limit clearable />
        </el-form-item>
        <el-form-item label="主机地址:" required>
          <el-input v-model="drawerData.SSH.nodeData.data.host" clearable />
        </el-form-item>
        <el-form-item label="端口:" required>
          <el-input v-model="drawerData.SSH.nodeData.data.port" clearable />
        </el-form-item>
        <el-form-item label="ssh密钥:" required>
          <el-select v-model="drawerData.SSH.nodeData.data.secretName" clearable placeholder="请选择密钥">
            <template #header>
              <el-row>
                <el-col :span="12">
                  <router-link :to="{name: 'secret'}" target="_blank">添加密钥</router-link>
                </el-col>
                <el-col :span="12" style="display: flex; justify-content: flex-end; align-items: center;">
                  <el-button :icon="Refresh" size="small" circle :loading="secretRefreshFlag" @click="handleSecretRefresh"/>
                </el-col>
              </el-row>
            </template>
            <el-option
                v-for="(item,index) in sshSecretList"
                :key="index"
                :label="item.name"
                :value="item.name"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="执行命令:" required>
          <el-input v-model="drawerData.SSH.nodeData.data.command" type="textarea" maxlength="300" clearable />
        </el-form-item>
        <el-form-item label="工作目录:">
          <el-input v-model="drawerData.SSH.nodeData.data.workDir" clearable />
        </el-form-item>
      </el-form>
    </el-drawer>

    <!-- SFTP -->
    <el-drawer v-model="drawerData.SFTP.drawerFlag" :direction="direction" size="500" :with-header="false">
      <el-form :model="drawerData.SFTP.nodeData" label-position="top">
        <el-form-item label="节点id:" required>
          <el-input v-model="drawerData.SFTP.nodeData.id" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点类型:" required>
          <el-input v-model="drawerData.SFTP.nodeData.type" disabled readonly/>
        </el-form-item>
        <el-form-item label="节点名称:" required>
          <el-input v-model="drawerData.SFTP.nodeData.title" maxlength="8" show-word-limit clearable />
        </el-form-item>
        <el-form-item label="主机地址:" required>
          <el-input v-model="drawerData.SFTP.nodeData.data.host" clearable />
        </el-form-item>
        <el-form-item label="端口:" required>
          <el-input v-model="drawerData.SFTP.nodeData.data.port" clearable />
        </el-form-item>
        <el-form-item label="ssh密钥:" required>
          <el-select v-model="drawerData.SFTP.nodeData.data.secretName" clearable placeholder="请选择密钥">
            <template #header>
              <el-row>
                <el-col :span="12">
                  <router-link :to="{name: 'secret'}" target="_blank">添加密钥</router-link>
                </el-col>
                <el-col :span="12" style="display: flex; justify-content: flex-end; align-items: center;">
                  <el-button :icon="Refresh" size="small" circle :loading="secretRefreshFlag" @click="handleSecretRefresh"/>
                </el-col>
              </el-row>
            </template>
            <el-option
                v-for="(item,index) in sshSecretList"
                :key="index"
                :label="item.name"
                :value="item.name"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="执行命令:" required>
          <el-input v-model="drawerData.SFTP.nodeData.data.command" type="textarea" maxlength="300" clearable />
        </el-form-item>
        <el-form-item label="工作目录:">
          <el-input v-model="drawerData.SFTP.nodeData.data.workDir" clearable />
        </el-form-item>
        <el-divider>
          <span style="color: #999;">传输文件列表配置</span>
        </el-divider>
        <template v-for="item in drawerData.SFTP.nodeData.data.fileList" :key="item.id">
          <div class="sftp-file-wrap clearfix">
            <el-badge class="mark sftp-del-btn"
                      value="删除"
                      @click.stop="handleDeleteFile(drawerData.SFTP.nodeData.data.fileList, item.id)"/>
            <el-form-item label="本地文件地址:" required>
              <el-input v-model="item.localPath" clearable />
            </el-form-item>
            <el-form-item label="远程文件地址:" required>
              <el-input v-model="item.remotePath" clearable />
            </el-form-item>
          </div>
        </template>
        <el-form-item>
          <el-button @click="handleAddFile(drawerData.SFTP.nodeData.data.fileList)">添加</el-button>
        </el-form-item>
      </el-form>
    </el-drawer>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, computed } from 'vue'
import {getTaskInfo, SaveTaskInfo, saveFlowData, getTaskTemplateList, saveTaskTemplate, deleteTaskTemplate,
  TaskTemplateParam, TaskTemplate
} from "@/api/TaskApi.ts"
import type { TaskInfo } from "@/api/TaskApi.ts";
import { useRoute } from 'vue-router'
import { ElLoading, ElMessage, ElMessageBox } from 'element-plus'
import { Refresh } from '@element-plus/icons-vue'
import {Graph, Node} from '@antv/x6'
import { getTeleport} from '@antv/x6-vue-shape'
import { handleRegisterNode, initEditGraph, initStencil } from "@/utils/AntvUtil.ts"
import {
  DockerData,
  GitData,
  MavenData,
  NodeData,
  SecretData,
  K8sData,
  NodeJsData,
  GoData,
  CmakeData,
  SSHData,
  SFTPData,
  FileData
} from "@/data/TaskData.ts";
import {NodeType} from "@/enum/NodeType.ts";
import { getSecretList } from "@/api/SecretApi.ts";
import {NodeStatus} from "@/enum/NodeStatus.ts";
import { nodeImageList, NodeImage } from '@/api/NodeApi.ts'
import { v4 as uuid } from 'uuid'

const route = useRoute()
const taskId = route.query.id as string
const taskInfo = ref<TaskInfo>({} as TaskInfo)
const graphDom = ref<HTMLElement>({} as HTMLElement)
const stencilDom = ref<HTMLElement>({} as HTMLElement)
let graph:Graph
const TeleportContainer = getTeleport()
const direction = ref<any>('rtl')
const secretList = ref<Array<SecretData>>([])
const secretRefreshFlag = ref<boolean>(false)
const templateList = ref<Array<TaskTemplate>>([])
const selectTemplate = ref<number>()
const imageList = ref<Array<NodeImage>>([])

const drawerData = ref({
  GIT: {
    drawerFlag: false,
    nodeData: {} as NodeData<GitData>
  },
  MAVEN: {
    drawerFlag: false,
    nodeData: {} as NodeData<MavenData>
  },
  DOCKER: {
    drawerFlag: false,
    nodeData: {} as NodeData<DockerData>
  },
  K8S: {
    drawerFlag: false,
    nodeData: {} as NodeData<K8sData>
  },
  NODEJS: {
    drawerFlag: false,
    nodeData: {} as NodeData<NodeJsData>
  },
  GO: {
    drawerFlag: false,
    nodeData: {} as NodeData<GoData>
  },
  CMAKE: {
    drawerFlag: false,
    nodeData: {} as NodeData<CmakeData>
  },
  SSH: {
    drawerFlag: false,
    nodeData: {} as NodeData<SSHData>
  },
  SFTP: {
    drawerFlag: false,
    nodeData: {} as NodeData<SFTPData>
  }
})

const gitSecretList = computed(() => {
  return secretList.value.filter(item => item.type === NodeType.GIT)
})

const dockerSecretList = computed(() => {
  return secretList.value.filter(item => item.type === NodeType.DOCKER)
})

const k8sSecretList = computed(() => {
  return secretList.value.filter(item => item.type === NodeType.K8S)
})

const sshSecretList = computed(() => {
  return secretList.value.filter(item => item.type === NodeType.SSH)
})

const mavenImages = computed(() => {
  return imageList.value.filter(item => item.type === NodeType.MAVEN)
})

const nodeImages = computed(() => {
  return imageList.value.filter(item => item.type === NodeType.NODEJS)
})

const goImages = computed(() => {
  return imageList.value.filter(item => item.type === NodeType.GO)
})

const cmakeImages = computed(() => {
  return imageList.value.filter(item => item.type === NodeType.CMAKE)
})

onMounted(() => {
  initWorkSpace()
})

const initWorkSpace = async () => {
  // 初始化任务数据
  await initTaskWork(taskId)
  // 注册节点
  handleRegisterNode()
  // 初始化画板
  graph = initEditGraph(graphDom.value, taskInfo.value)
  // 初始化节点面板
  initStencil(stencilDom.value, graph)
  // 初始化画板事件
  initGraphEvent(graph)
  await handleSecretList()
  await queryTemplateList()
  await queryImage()
}

const initTaskWork = async (taskId:string) => {
  if(!taskId){
    return
  }
  const loading = getLoading('流程数据加载中...')
  const res = await getTaskInfo(taskId, true)
  loading.close()
  if(res.data){
    taskInfo.value = res.data
  }
}

/**
 * 初始化画板事件
 */
const initGraphEvent = (graph: Graph) => {
  graph.on('node:mouseenter', ({ node }) => {
    handleAddNodeTools(node)
  })

  graph.on('node:mouseleave', ({ node }) => {
    node.removeTools()
  })

  graph.on('edge:click', ({ edge }) => {
    if(edge.hasTools()){
      edge.removeTools()
      return
    }

    edge.addTools([
      {
        name: 'button-remove',
      },
    ])
  })

  graph.on('edge:unselected', ({ edge }) => {
    if(edge.hasTools()){
      edge.removeTools()
    }
  })

  graph.on('node:added', ({ node }) => {
    handleAddNodePort(node)
  })

  graph.on('node:click', ({ node }) => {
    setCurrentNodeData(node)
  })
}

const handleAddNodeTools = (node: Node) => {
  node.addTools([
    {
      name: 'boundary',
      args: {
        attrs: {
          fill: '#ffffff',
          stroke: '#333',
          'stroke-width': 1,
          'fill-opacity': 0.2,
        },
      },
    },
    {
      name: 'button-remove',
      args: {
        x: 0,
        y: 0,
        offset: { x: 110, y: 1 },
      },
    },
  ])
}

const handleAddNodePort = (node: Node) => {
  // 判断是否端口
  if(node.getPorts().length > 0){
    return
  }

  node.addPorts([
    {
      group: 'left',
    },
    {
      group: 'right',
    }
  ])
}

const getLoading = (msg:string):any  =>{
  return ElLoading.service({
    lock: true,
    text: msg,
    background: 'rgba(0, 0, 0, 0.7)',
  })
}

const setCurrentNodeData = (node: Node) => {
  const data = node.getData() as NodeData;
  const handler = nodeHandleMap.get(data.type)
  handler && handler(data, node.id)
}

const nodeHandleMap = new Map<string, Function>()
nodeHandleMap.set(NodeType.GIT, (data: NodeData, nodeId:string) => {
  drawerData.value.GIT.nodeData = data
  drawerData.value.GIT.drawerFlag = true
  drawerData.value.GIT.nodeData.id = nodeId
})

nodeHandleMap.set(NodeType.MAVEN, (data: NodeData, nodeId:string) => {
  drawerData.value.MAVEN.nodeData = data
  drawerData.value.MAVEN.drawerFlag = true
  drawerData.value.MAVEN.nodeData.id = nodeId
})

nodeHandleMap.set(NodeType.DOCKER, (data: NodeData, nodeId:string) => {
  drawerData.value.DOCKER.nodeData = data
  drawerData.value.DOCKER.drawerFlag = true
  drawerData.value.DOCKER.nodeData.id = nodeId
})

nodeHandleMap.set(NodeType.K8S, (data: NodeData, nodeId:string) => {
  drawerData.value.K8S.nodeData = data
  drawerData.value.K8S.drawerFlag = true
  drawerData.value.K8S.nodeData.id = nodeId
})

nodeHandleMap.set(NodeType.NODEJS, (data: NodeData, nodeId:string) => {
  drawerData.value.NODEJS.nodeData = data
  drawerData.value.NODEJS.drawerFlag = true
  drawerData.value.NODEJS.nodeData.id = nodeId
})

nodeHandleMap.set(NodeType.GO, (data: NodeData, nodeId:string) => {
  drawerData.value.GO.nodeData = data
  drawerData.value.GO.drawerFlag = true
  drawerData.value.GO.nodeData.id = nodeId
})

nodeHandleMap.set(NodeType.CMAKE, (data: NodeData, nodeId:string) => {
  drawerData.value.CMAKE.nodeData = data
  drawerData.value.CMAKE.drawerFlag = true
  drawerData.value.CMAKE.nodeData.id = nodeId
})

nodeHandleMap.set(NodeType.SSH, (data: NodeData, nodeId:string) => {
  drawerData.value.SSH.nodeData = data
  drawerData.value.SSH.drawerFlag = true
  drawerData.value.SSH.nodeData.id = nodeId
})

nodeHandleMap.set(NodeType.SFTP, (data: NodeData, nodeId:string) => {
  drawerData.value.SFTP.nodeData = data
  drawerData.value.SFTP.drawerFlag = true
  drawerData.value.SFTP.nodeData.id = nodeId
})

const handleSecretRefresh = async () => {
  secretRefreshFlag.value = true
  await handleSecretList()
  secretRefreshFlag.value = false
}

const handleImageRefresh = async () => {
  secretRefreshFlag.value = true
  await queryImage()
  secretRefreshFlag.value = false
}

const handleSecretList = async () => {
  const rs = await getSecretList(null)
  secretList.value = rs.data ? rs.data : []
}

const handleSaveFlow = async () => {
  const data = graph.toJSON({ diff: true })
  if(data.cells.length <= 0){
    ElMessage.error('没有流程节点')
    return
  }

  graph.getNodes().forEach(i => i.data.id = i.id)

  const rootNodes:Node[] = graph.getRootNodes()
  if(rootNodes.length > 1){
    ElMessage.error('只能有一个根节点')
    return
  }

  const rootNode: Node = rootNodes[0]
  const list: NodeData[] = []
  list.push(rootNode.data)

  if(graph.getNeighbors(rootNode).length > 1){
    ElMessage.error('暂不支持多分支')
    return
  }

  const childNodes = graph.getSuccessors(rootNode, { deep: true }) as Node[]
  if(childNodes){
    childNodes.forEach(i => list.push(i.data))
  }

  const loading = getLoading('正在保存数据...')

  const flowData = JSON.stringify(data)
  const saveTaskInfo:SaveTaskInfo = {
    id: taskInfo.value.id,
    flowData: flowData,
    taskDataList: list
  }
  const rs = await saveFlowData(saveTaskInfo)
  loading.close()
  if(rs.code === '200'){
    taskInfo.value.flowData = flowData
    taskInfo.value.taskDataList = list
    ElMessage.success('保存成功')
  }
}

const handleSaveTemplate = () => {
  ElMessageBox.prompt('请输入模版名称', '保存模版', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
  }).then(async ({ value }) => {
    if(!value){
      ElMessage.error("请输入模版名称")
      return
    }

    const data = graph.toJSON({ diff: true })
    if(data.cells.length <= 0){
      ElMessage.error('没有流程节点')
      return
    }

    graph.getNodes().forEach(i => i.data.id = i.id)

    const rootNodes:Node[] = graph.getRootNodes()
    if(rootNodes.length > 1){
      ElMessage.error('只能有一个根节点')
      return
    }

    const rootNode: Node = rootNodes[0]
    const list: NodeData[] = []
    list.push(rootNode.data)

    if(graph.getNeighbors(rootNode).length > 1){
      ElMessage.error('暂不支持多分支')
      return
    }

    const childNodes = graph.getSuccessors(rootNode, { deep: true }) as Node[]
    if(childNodes){
      childNodes.forEach(i => list.push(i.data))
    }

    const loading = getLoading('正在保存数据...')

    const flowData = JSON.stringify(data)
    const param:TaskTemplateParam = {
      name: value,
      flowData: flowData
    }
    const rs = await saveTaskTemplate(param)
    loading.close()
    if(rs.code === '200'){
      ElMessage.success('保存成功')
      await queryTemplateList()
    }
  }).catch(() => {

  })
}

const queryTemplateList = async () => {
  const rs = await getTaskTemplateList()
  templateList.value = rs.data ? rs.data : []
}

const templateChange = () => {
  const data = templateList.value.find(i => i.id === selectTemplate.value)
  if(!data){
    return
  }

  graph.fromJSON(JSON.parse(data.flowData))
  graph.getNodes().forEach(i => {
    i.data.status = NodeStatus.INIT
  })
  graph.centerContent()
}

const handleDeleteTemplate = async (id:number) => {
  await deleteTaskTemplate(id)
  await queryTemplateList()
  if(selectTemplate.value == id){
    selectTemplate.value = 0
  }
}

const queryImage = async () => {
  const rs = await nodeImageList(null)
  imageList.value = rs.data ? rs.data : []
}

const handleAddFile = (data: Array<FileData>) => {
  data.push({
    id: uuid(),
    localPath: '',
    remotePath: '',
  })
}

const handleDeleteFile = (data: Array<FileData>, id: string) => {
  if (data.length <= 1) {
    ElMessage.error("至少保留一个文件配置")
    return
  }

  data.slice(data.findIndex(i => i.id === id), 1)
}
</script>

<style lang="less" scoped>
.main-wrap{
  padding: 20px;

  .top-wrap{
    display: flex;
    justify-content: flex-start;
    height: 110px;

    .left-wrap{
      padding-left: 10px;
      padding-right: 10px;

      .task-text{
        color: #409eff;
      }
    }

    .right-wrap{
      flex-grow: 1;
      flex-basis: auto;
      display: flex;
      justify-content: flex-end;
      align-items: self-end;
      padding-right: 2px;
    }
  }

  .task-flow-wrap{
    display: flex;
    margin-top: 10px;
    padding-left: 8px;
    height: calc(100vh - 210px);
    font-family: sans-serif;

    .app-stencil {
      position: relative;
      width: 250px;
      border: 1px solid #ede6e6;
    }

    .app-content {
      flex: 1;
      height: calc(100vh - 210px);
      box-shadow: 0 0 10px 1px #e9e9e9;
      border-radius: 8px;
      margin-left: 10px;
    }
  }

  .sftp-file-wrap {
    width: 450px;
    padding: 10px;
    border: #2b85e4 solid 1px;
    border-radius: 10px;
    margin-bottom: 10px;

    .sftp-del-btn {
      cursor: pointer;
      float: right;
    }
  }

}
</style>